#include <iostream>
#include <string>
#include <vector>

#include "z80mem.h"
#include "z80cpu.h"
#include "z80.h"
#include "defines.h"
#include "tables.h"
#include "..//GenTables//itables.h"

#define USERBUF 255

z80CPU::z80CPU()
{
	mem = new z80Mem();
	RESET();
}

void z80CPU::hook(read_func_ptr read_ptr, write_func_ptr write_ptr)
{
	read = read_ptr;
	write = write_ptr;
}
void z80CPU::setFile(std::string file)
{
	mem->load(file);
	RESET();
}

void z80CPU::RESET(void)
{
	halt = 0;

    AF.reg.A = 0x0;
    AF.reg.F = F_INIT;
    
    BC.pair = 0x0;
    DE.pair = 0x0;
    HL.pair = 0x0;

    PC.pair = 0x0;    

    SP.pair = SP_INIT;    

}

int z80CPU::exec(int cycles)
{
	byte tmp_b;
	pair(high, low,tmp_w);
	unsigned int tmp_d;

	while (cycles >= TCycles[PC.pair])
	{
		if (!halt)
		{
			cycles -= TCycles[PC.pair];

			switch (MemReadB(PC.pair))
			{
				#include "instructions.h"
			}			
		}
	}
	return cycles;
}

char b16(char k)
{
	if (k >= '0' && k <= '9') k -= 48;
	else if (k >= 'A' && k <= 'F') k -= 55;
	else if (k >= 'a' && k <= 'f') k -= 87;
	else return -1;
	return k;
}
char base16(char *ptr)
{
	return (b16(ptr[0]) << 4)+b16(ptr[1]);
}


void z80CPU::user()
{
	byte tmp_b;
	pair(high, low,tmp_w);
	unsigned int tmp_d;

	byte inst = 0;

	char *buf = (char*)malloc(USERBUF);

	while (!halt)
	{
		std::cin >> buf;

		PC.pair = 0;

		for ( int i = 0, s = 0; buf[s] != '\r' && buf[s] != '\n' && buf[s] ; ++i, s+=2)
		{
			mem->write(i,base16(buf+s));
		}

		while (!halt)
		{
			inst = MemReadB(PC.pair);
			printf ("cycles: %d, %s | A=%x F=%x BC=%x DE=%x HL=%x PC=%x SP=%x\r\n", 
				TCycles[inst], Mnemonics[inst],AF.reg.A,AF.reg.F,BC.pair,DE.pair,HL.pair,PC.pair,SP.pair);

			switch (inst)
			{
				#include "instructions.h"
			}
		}
	}

	free(buf);
}
